var Log = require('../../../util/logger');
var path = require('path');
var util = require('../../../util/index');
var notify = require('../../notify/ui');
var fs = require('fs');
var frac = require('../../../util/frac');

var ret = {
	getNote: function(filepath){
		var raw = fs.readFileSync(filepath, {encoding:'utf8'});
		if(!raw){
			return null;
		}
		//把所有的文件去掉扩展名
		var _dir = path.dirname(filepath);
		var fileMap = util.getFileMapping(_dir);

		var lines = raw.split(/\n|\r\n/g);
		var ret = {};
		this.bpmDict = {};
		this.wavDict = {};

		ret.meta = {
			mode: 0    //目前默认bms导入都是key模式
		};
		ret.time = [];
		ret.note = [];
		ret.extra = {};
		ret.extra.samples = [];

		var mcBeat = 0;
		var currSig = 4;
		var currSec = 0;
		var pendingNotes = [];
		var maxCol = 0;
		var toggle = [0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0];

		for(var i=0;i<lines.length;i++){
			var line = lines[i].trim();
			if(line.length == 0){
				continue;
			}
			if(line.charAt(0) != '#'){
				continue;
			}
			var idx = line.indexOf(':');
			if(idx == 6){
				var key = line.substring(1, idx);
				var val = line.substring(idx+1);
				var section = +key.substring(0, 3);
				var channel = +key.substring(3);
				if(section != currSec){
					mcBeat += currSig;
					if(section - currSec > 1){
						//跳过了若干节
						mcBeat += (section - currSec - 1) * 4;//后面的sig都是4
					}
					currSec = section;
					currSig = 4;  //每个新节都恢复到4
				}
				switch(channel){
					case 1:{
						var len = val.length;
						for (var sub = 0; sub + 1 < len; sub+=2)
						{
							var obj = val.substring(sub, sub+2);
							if (obj.length != 2 || obj == '00')
								continue;
							if(!this.wavDict[obj]){
								continue;
							}
							var _beat = mcBeat + (sub / len)*currSig;
							var beat = frac.reduce(frac.fromFloat(_beat, 288));
							ret.note.push({
								beat: beat,
								type: 1,
								sound: fileMap[util.lowerCaseRemoveExt(this.wavDict[obj])]
							});
							//column暂时不填

						}
					}
						break;
					case 2:{
						currSig = parseFloat(val) * 4;
					}
						break;
					case 3:{
						var len = val.length;
						for (var sub = 0; sub + 1 < len; sub+=2)
						{
							var obj = val.substring(sub, sub+2);
							if (obj.length != 2 || obj == '00')
								continue;
							var _beat = mcBeat + (sub / len)*currSig;
							var beat = frac.reduce(frac.fromFloat(_beat, 288));
							ret.time.push({
								beat: beat,
								bpm: parseInt(obj, 16)
							});

						}

					}
						break;
					case 8:{
						if(!this.bpmDict[val]){
							continue;
						}

						ret.time.push({
							beat: frac.reduce(frac.fromFloat(mcBeat, 288)),
							bpm: this.bpmDict[val]
						});
					}
						break;
					default :{
						var col = this.channelToColumn(channel);
						if(col < 0){
							continue;
						}
						var len = val.length;
						var isLong = channel >= 51;
						for (var sub = 0; sub + 1 < len; sub+=2)
						{
							var obj = val.substring(sub, sub+2);
							if (obj.length != 2 || obj == '00')
								continue;

							var _beat = mcBeat + (sub / len)*currSig;
							var beat = frac.reduce(frac.fromFloat(_beat, 288));

							if(!isLong){
								if (this.longType == 2 && this.longObj && obj == this.longObj && pendingNotes[col])
								{
									var note = pendingNotes[col];
									note.endbeat = beat;
									pendingNotes[col] = null;
									continue;
								}
							}else{
								if (pendingNotes[col])
								{
									var note = pendingNotes[col];
									note.endbeat = beat;
									pendingNotes[col] = null;
									continue;
								}
							}

							var note = {
								beat: beat,
								column: col
							};
							if(this.wavDict[obj]){
								note.sound = fileMap[util.lowerCaseRemoveExt(this.wavDict[obj])];
							}
							ret.note.push(note);

							if(!isLong){
								if(this.longType == 2){
									pendingNotes[col] = note;
								}
							}else{
								pendingNotes[col] = note;
							}
							if(col > maxCol){
								maxCol = col;
							}
							toggle[col] = 1;
						}
						break;
					}
				}
				continue;
			}
			idx = line.indexOf(' ');
			if(idx > 0){
				var key = line.substring(1, idx);
				var val = line.substring(idx + 1);
				if(key == 'BPM'){
					ret.time.push({
						beat:[0,0,4],
						bpm: parseFloat(val)
					});
				}else if(key == 'TITLE'){
					util.setJsonChainValue(ret, 'meta.song.title', val);
				}else if(key == 'ARTIST'){
					util.setJsonChainValue(ret, 'meta.song.artist', val);
				}else if(key == 'CREATOR'){
					ret.meta.creator = val;
				}else if(key == 'STAGEFILE') {
					ret.meta.background = val;
				}else if(key == 'LNTYPE') {
					this.longType = +val;
				}else if(key == 'LNOBJ'){
					this.longObj = val;
				}else if(key.indexOf('BPM') == 0){
					this.bpmDict[key.substring(3)] = parseFloat(val);
				}else if(key.indexOf('WAV') == 0){
					val = fileMap[util.lowerCaseRemoveExt(val)];
					this.wavDict[key.substring(3)] = val;
					ret.extra.samples.push({
						name: val
					})
				}
			}
		}

		maxCol += 1; //从1开始

		//toggle前面有几个0, 就把note往左移动多少
		var idx = 0;
		while(idx < 15 && toggle[idx] == 0){
			idx++;
		}
		if(idx == 15){
			Log.e("holy shit", "BMS");
			return null;
		}else if(idx != 0){
			maxCol -= idx;
			for(var i=0;i<15;i++){
				if(i < maxCol){
					toggle[i] = 1;
				}else{
					toggle[i] = 0;
				}
			}
		}

		//再处理音频note, 放到可用的轨道上
		//极限情况下, 轨道是不够用的
		var rest = 15 - maxCol;
		var lastBeat = [0,0,4];
		var offsetIdx = 0;
		for(var i=ret.note.length-1;i>=0;i--){
			var note = ret.note[i];
			//普通note修正轨道
			if(note.type != 1) {
				note.column -= idx;
				continue;
			}
			if(frac.compare(lastBeat, note.beat) == 0){
				if(rest <= 1){
					note.column = maxCol;
				}else{
					note.column = maxCol + offsetIdx;
					offsetIdx++;
					if(offsetIdx >= rest){
						offsetIdx = 0;
					}
				}
			}else{
				note.column = maxCol;
				offsetIdx = 0;
			}
			lastBeat = note.beat;
			toggle[note.column] = 2;
		}

		util.setJsonChainValue(ret, 'meta.mode_ext.column', maxCol);
		ret.extra.toggle = toggle;

		return ret;
	},

	//channel 转 column
	channelToColumn: function(chan){
		if(chan >= 11 && chan <=19){
			chan -= 11;
		}else if(chan >= 21 && chan <= 29){
			chan -= 21;
		}else if(chan >= 51 && chan <= 59){
			chan -= 51;
		}else if(chan >= 61 && chan <= 69){
			chan -= 61;
		}else{
			return -1;
		}
		// 0->1  4->5 5->0 8->6 9->7
		//没有17 27 57 67
		if(chan == 5){
			return 0;
		}else if(chan < 5){
			return chan + 1;
		}else{
			return chan - 1;
		}
	},

	mapFile : function(fn){

	}
};

module.exports = ret;